package feizhou.untils.tools;

import java.math.BigDecimal;

/**
 * @description: 求两组经纬度之间的距离
 * @author: lijiayu
 * @date: 2019-12-14 15:33
 **/
public class HarvenSinUtil {

    static double EARTH_RADIUS = 6371.0;//km 地球半径 平均值，千米

    /**
     * 返回两组经纬度之间的距离，单位千米
     *
     * @param lat1
     * @param lon1
     * @param lat2
     * @param lon2
     * @return
     */
    public static double distance(double lat1, double lon1, double lat2, double lon2) {
        //用haversine公式计算球面两点间的距离。
        //经纬度转换成弧度
        lat1 = convertDegreesToRadians(lat1);
        lon1 = convertDegreesToRadians(lon1);
        lat2 = convertDegreesToRadians(lat2);
        lon2 = convertDegreesToRadians(lon2);

        //差值
        double vLon = Math.abs(lon1 - lon2);
        double vLat = Math.abs(lat1 - lat2);

        //h is the great circle distance in radians, great circle就是一个球体上的切面，它的圆心即是球心的一个周长最大的圆。
        double h = HaverSin(vLat) + Math.cos(lat1) * Math.cos(lat2) * HaverSin(vLon);

        double distance = 2 * EARTH_RADIUS * Math.asin(Math.sqrt(h));
        return distance;
    }

    /**
     * 返回两组经纬度之间的距离，单位千米 保留4位小数点
     *
     * @param lat1
     * @param lon1
     * @param lat2
     * @param lon2
     * @return
     */
    public static double distance4Pricesion(double lat1, double lon1, double lat2, double lon2) {
        double distance = distance(lat1, lon1, lat2, lon2);
        // 单位转为米，并保留两位小数点
        BigDecimal bd = new BigDecimal(distance);
        distance = bd.setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
        return distance;
    }

    /**
     * 返回两组经纬度之间的距离，单位转为米，并保留两位小数点
     *
     * @param lat1
     * @param lon1
     * @param lat2
     * @param lon2
     * @return
     */
    public static double distanceToMeter(double lat1, double lon1, double lat2, double lon2) {
        double distance = distance(lat1, lon1, lat2, lon2) * 1000;
        // 单位转为米，并保留两位小数点
        BigDecimal bd = new BigDecimal(distance);
        distance = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        return distance;
    }

    public static double HaverSin(double theta) {
        double v = Math.sin(theta / 2);
        return v * v;
    }

    /**
     * 将角度换算为弧度。
     *
     * @param degrees
     * @return
     */
    public static double convertDegreesToRadians(double degrees) {
        return degrees * Math.PI / 180;
    }

    public static double convertRadiansToDegrees(double radian) {
        return radian * 180.0 / Math.PI;
    }

    public static void main(String[] args) {
        double d1 = distance(39.94607, 116.32793, 31.24063, 121.42575);
        System.out.println(d1);
        d1 = distanceToMeter(34.27, 108.93, 31.24063, 121.42575);
        System.out.println(d1);
        d1 = distance(29.490295, 106.486654, 29.615467, 106.581515);
        System.out.println(d1);
        d1 = distanceToMeter(29.490295, 106.486654, 29.615467, 106.581515);
        System.out.println(d1);
    }

}
